﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Memcached.ClientLibrary;
using System.Configuration;
using CSP.Common.Tools;

namespace CSP.Common.CacheManage
{
    public class SockIOPoolFactory
    {
        private SockIOPool _sockIOPool;

        private string[] _serverList = { "127.0.0.1" };

        private int _initConnections = 3;

        private int _minConnections = 3;

        private int _maxConnections = 5;

        private int _socketConnectTimeout = 1000;

        private int _socketTimeout = 3000;

        private int _maintenanceSleep = 30;

        private bool _failover = true;

        private bool _nagle = false;

        private static SockIOPoolFactory _sockIOPoolFactory;

        /// <summary>
        /// 初始化连接池的数量
        /// </summary>
        public int InitConnections
        {
            get
            {
                return _initConnections;
            }
            set
            {
                _initConnections = value;
            }
        }

        /// <summary>
        /// 每个服务器建立最小的连接数，当自查线程发现与某个服务器建立连接数目小于这个数目时
        /// 会弥补剩下的连接
        /// </summary>
        public int MinConnections
        {
            get
            {
                return _minConnections;
            }
            set
            {
                _minConnections = value;
            }
        }

        /// <summary>
        /// 每个服务器建立最大的连接数，当自查线程发现与某个服务器建立连接数目大于这个数目
        ///时就会逐个检查这些连接的空闲时间是否大于maxConn，如果大于会关闭这些连接，直到连接数等于maxConn
        /// </summary>
        public int MaxConnections
        {
            get
            {
                return _maxConnections;
            }
            set
            {
                _maxConnections = value;
            }
        }

        /// <summary>
        /// 通讯连接延迟时间
        /// </summary>
        public int SocketConnectTimeout
        {
            get
            {
                return _socketConnectTimeout;
            }
            set
            {
                _socketConnectTimeout = value;
            }
        }

        /// <summary>
        /// 通讯中延迟时间
        /// </summary>
        public int SocketTimeout
        {
            get
            {
                return _socketTimeout;
            }
            set
            {
                _socketTimeout = value;
            }
        }

        /// <summary>
        /// 自查线程周期进行工作，其每次休眠时间
        /// </summary>
        public int MaintenanceSleep
        {
            get
            {
                return _maintenanceSleep;
            }
            set
            {
                _maintenanceSleep = value;
            }
        }

        /// <summary>
        /// 则直接返回不再尝试连接到其他机器了；否则会组装一些新的key到hash bucket里去找剩
        ///下的服务器地址按2建立连接。
        /// </summary>
        public bool Failover
        {
            get
            {
                return _failover;
            }
            set
            {
                _failover = value;
            }
        }

        /// <summary>
        /// Socket的参数，如果是true在写数据时不缓冲，立即发送出去
        /// </summary>
        public bool Nagle
        {
            get
            {
                return _nagle;
            }
            set
            {
                _nagle = value;
            }
        }

        public static SockIOPoolFactory GetInstance()
        {
            if (_sockIOPoolFactory == null)
            {
                _sockIOPoolFactory = new SockIOPoolFactory();
            }

            return _sockIOPoolFactory;
        }

        private SockIOPoolFactory()
        {

            _sockIOPool = SockIOPool.GetInstance();

            this.Init();
        }

        /// <summary>
        /// 初始化启动
        /// </summary>
        private void Init()
        {
            _serverList = ConfigurationManager.AppSettings["Memcached.ServerList"].Split(',');

            CheckIPAndPorts(_serverList);

            _sockIOPool.SetServers(_serverList);
            _sockIOPool.Initialize();
        }

        /// <summary>
        /// 重启连接池
        /// </summary>
        public void Restart()
        {
            this.Dispose();
            this.Init();
        }

        /// <summary>
        /// 关闭释放连接池
        /// </summary>
        public void Dispose()
        {
            //如果没有启动则不需要释放
            if (_sockIOPool.Initialized)
            {
                _sockIOPool.Shutdown();
            }
        }


        /// <summary>
        /// ip 格式验证
        /// </summary>
        /// <param name="ips"></param>
        private void CheckIPAndPorts(string[] ips)
        {
            for (int i = 0; i < ips.Length; i++)
            {
                if (!CommonTool.CheckIPAndPort(ips[i]))
                {
                    throw new Exception("配置文件MemCache.Servlist 格式不正确，请检查配置文件");
                }
            }

        }
    }
}
